home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / var / lib / python-support / python2.6 / cupshelpers / cupshelpers.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-10-12  |  23.6 KB  |  778 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import cups
  5. import pprint
  6. import os
  7. import tempfile
  8. import re
  9. import string
  10. import locale
  11. from  import _debugprint
  12.  
  13. class Printer:
  14.     _flags_blacklist = [
  15.         'options',
  16.         'local']
  17.     
  18.     def __init__(self, name, connection, **kw):
  19.         '''
  20.         @param name: printer name
  21.         @type name: string
  22.         @param connection: CUPS connection
  23.         @type connection: CUPS.Connection object
  24.         @param kw: printer attributes
  25.         @type kw: dict indexed by string
  26.         '''
  27.         self.name = name
  28.         self.connection = connection
  29.         self.class_members = []
  30.         self.update(**kw)
  31.         self._ppd = None
  32.  
  33.     
  34.     def __del__(self):
  35.         if self._ppd != None:
  36.             os.unlink(self._ppd)
  37.         
  38.  
  39.     
  40.     def __repr__(self):
  41.         return '<cupshelpers.Printer "%s">' % self.name
  42.  
  43.     
  44.     def _expand_flags(self):
  45.         
  46.         def _ascii_lower(str):
  47.             return str.translate(string.maketrans(string.ascii_uppercase, string.ascii_lowercase))
  48.  
  49.         prefix = 'CUPS_PRINTER_'
  50.         prefix_length = len(prefix)
  51.         for name in cups.__dict__:
  52.             if name.startswith(prefix):
  53.                 attr_name = _ascii_lower(name[prefix_length:])
  54.                 if attr_name in self._flags_blacklist:
  55.                     continue
  56.                 
  57.                 if attr_name == 'class':
  58.                     attr_name = 'is_class'
  59.                 
  60.                 setattr(self, attr_name, bool(self.type & getattr(cups, name)))
  61.                 continue
  62.         
  63.  
  64.     
  65.     def update(self, **kw):
  66.         '''
  67.         Update object from printer attributes.
  68.  
  69.         @param kw: printer attributes
  70.         @type kw: dict indexed by string
  71.         '''
  72.         self.state = kw.get('printer-state', 0)
  73.         self.enabled = self.state != cups.IPP_PRINTER_STOPPED
  74.         self.device_uri = kw.get('device-uri', '')
  75.         self.info = kw.get('printer-info', '')
  76.         self.is_shared = kw.get('printer-is-shared', None)
  77.         self.location = kw.get('printer-location', '')
  78.         self.make_and_model = kw.get('printer-make-and-model', '')
  79.         self.type = kw.get('printer-type', 0)
  80.         self.uri_supported = kw.get('printer-uri-supported', '')
  81.         if type(self.uri_supported) != list:
  82.             self.uri_supported = [
  83.                 self.uri_supported]
  84.         
  85.         self._expand_flags()
  86.         if self.is_shared is None:
  87.             self.is_shared = not (self.not_shared)
  88.         
  89.         del self.not_shared
  90.  
  91.     
  92.     def getAttributes(self):
  93.         '''
  94.         Fetch further attributes for the printer.
  95.  
  96.         Normally only a small set of attributes is fetched.  This
  97.         method is for fetching more.
  98.         '''
  99.         attrs = self.connection.getPrinterAttributes(self.name)
  100.         self.attributes = { }
  101.         self.other_attributes = { }
  102.         self.possible_attributes = {
  103.             'landscape': ('False', [
  104.                 'True',
  105.                 'False']),
  106.             'page-border': ('none', [
  107.                 'none',
  108.                 'single',
  109.                 'single-thick',
  110.                 'double',
  111.                 'double-thick']) }
  112.         for key, value in attrs.iteritems():
  113.             if key.endswith('-default'):
  114.                 name = key[:-len('-default')]
  115.                 if name in ('job-sheets', 'printer-error-policy', 'printer-op-policy', 'notify-events', 'document-format', 'notify-lease-duration'):
  116.                     continue
  117.                 
  118.                 if not attrs.get(name + '-supported', None) and self.possible_attributes.get(name, None):
  119.                     pass
  120.                 supported = ''
  121.                 if isinstance(value, list):
  122.                     value = reduce((lambda x, y: x + ',' + y), value)
  123.                 
  124.                 self.attributes[name] = value
  125.                 if attrs.has_key(name + '-supported'):
  126.                     supported = attrs[name + '-supported']
  127.                     self.possible_attributes[name] = (value, supported)
  128.                 
  129.             attrs.has_key(name + '-supported')
  130.             if not key.endswith('-supported') and key != 'job-sheets-default' and key != 'printer-error-policy' and key != 'printer-op-policy' and not key.startswith('requesting-user-name-'):
  131.                 self.other_attributes[key] = value
  132.                 continue
  133.         
  134.         (self.job_sheet_start, self.job_sheet_end) = attrs.get('job-sheets-default', ('none', 'none'))
  135.         self.job_sheets_supported = attrs.get('job-sheets-supported', [
  136.             'none'])
  137.         self.error_policy = attrs.get('printer-error-policy', 'none')
  138.         self.error_policy_supported = attrs.get('printer-error-policy-supported', [
  139.             'none'])
  140.         if not attrs.get('printer-op-policy', ''):
  141.             pass
  142.         self.op_policy = 'default'
  143.         self.op_policy_supported = attrs.get('printer-op-policy-supported', [
  144.             'default'])
  145.         self.default_allow = True
  146.         self.except_users = []
  147.         if attrs.has_key('requesting-user-name-allowed'):
  148.             self.except_users = attrs['requesting-user-name-allowed']
  149.             self.default_allow = False
  150.         elif attrs.has_key('requesting-user-name-denied'):
  151.             self.except_users = attrs['requesting-user-name-denied']
  152.         
  153.         self.except_users_string = ', '.join(self.except_users)
  154.         if attrs.has_key('device-uri') and attrs['device-uri'].startswith('smb:'):
  155.             attrs['device-uri'] = self.device_uri
  156.         
  157.         self.update(**attrs)
  158.  
  159.     
  160.     def getServer(self):
  161.         '''
  162.         Find out which server defines this printer.
  163.  
  164.         @returns: server URI or None
  165.         '''
  166.         if not self.uri_supported[0].startswith('ipp://'):
  167.             return None
  168.         uri = self.uri_supported[0][6:]
  169.         uri = uri.split('/')[0]
  170.         uri = uri.split(':')[0]
  171.         if uri == 'localhost.localdomain':
  172.             uri = 'localhost'
  173.         
  174.         return uri
  175.  
  176.     
  177.     def getPPD(self):
  178.         """
  179.         Obtain the printer's PPD.
  180.  
  181.         @returns: cups.PPD object, or False for raw queues
  182.         @raise cups.IPPError: IPP error
  183.         """
  184.         result = None
  185.         if self._ppd is None:
  186.             
  187.             try:
  188.                 self._ppd = self.connection.getPPD(self.name)
  189.                 result = cups.PPD(self._ppd)
  190.             except cups.IPPError:
  191.                 (e, m) = None
  192.                 if e == cups.IPP_NOT_FOUND:
  193.                     result = False
  194.                 else:
  195.                     raise 
  196.                 e == cups.IPP_NOT_FOUND
  197.             
  198.  
  199.         None<EXCEPTION MATCH>cups.IPPError
  200.         if result != False and self._ppd != None:
  201.             result = cups.PPD(self._ppd)
  202.         
  203.         return result
  204.  
  205.     
  206.     def setOption(self, name, value):
  207.         """
  208.         Set a printer's option.
  209.  
  210.         @param name: option name
  211.         @type name: string
  212.         @param value: option value
  213.         @type value: option-specific
  214.         """
  215.         if isinstance(value, float):
  216.             radixchar = locale.nl_langinfo(locale.RADIXCHAR)
  217.             if radixchar != '.':
  218.                 value = str(value).replace(radixchar, '.')
  219.             
  220.         
  221.         self.connection.addPrinterOptionDefault(self.name, name, value)
  222.  
  223.     
  224.     def unsetOption(self, name):
  225.         """
  226.         Unset a printer's option.
  227.  
  228.         @param name: option name
  229.         @type name: string
  230.         """
  231.         self.connection.deletePrinterOptionDefault(self.name, name)
  232.  
  233.     
  234.     def setEnabled(self, on, reason = None):
  235.         """
  236.         Set the printer's enabled state.
  237.  
  238.         @param on: whether it will be enabled
  239.         @type on: bool
  240.         @param reason: reason for this state
  241.         @type reason: string
  242.         """
  243.         if on:
  244.             self.connection.enablePrinter(self.name)
  245.         elif reason:
  246.             self.connection.disablePrinter(self.name, reason = reason)
  247.         else:
  248.             self.connection.disablePrinter(self.name)
  249.  
  250.     
  251.     def setAccepting(self, on, reason = None):
  252.         """
  253.         Set the printer's accepting state.
  254.  
  255.         @param on: whether it will be accepting
  256.         @type on: bool
  257.         @param reason: reason for this state
  258.         @type reason: string
  259.         """
  260.         if on:
  261.             self.connection.acceptJobs(self.name)
  262.         elif reason:
  263.             self.connection.rejectJobs(self.name, reason = reason)
  264.         else:
  265.             self.connection.rejectJobs(self.name)
  266.  
  267.     
  268.     def setShared(self, on):
  269.         """
  270.         Set the printer's shared state.
  271.  
  272.         @param on: whether it will be accepting
  273.         @type on: bool
  274.         """
  275.         self.connection.setPrinterShared(self.name, on)
  276.  
  277.     
  278.     def setErrorPolicy(self, policy):
  279.         """
  280.         Set the printer's error policy.
  281.  
  282.         @param policy: error policy
  283.         @type policy: string
  284.         """
  285.         self.connection.setPrinterErrorPolicy(self.name, policy)
  286.  
  287.     
  288.     def setOperationPolicy(self, policy):
  289.         """
  290.         Set the printer's operation policy.
  291.  
  292.         @param policy: operation policy
  293.         @type policy: string
  294.         """
  295.         self.connection.setPrinterOpPolicy(self.name, policy)
  296.  
  297.     
  298.     def setJobSheets(self, start, end):
  299.         """
  300.         Set the printer's job sheets.
  301.  
  302.         @param start: start sheet
  303.         @type start: string
  304.         @param end: end sheet
  305.         @type end: string
  306.         """
  307.         self.connection.setPrinterJobSheets(self.name, start, end)
  308.  
  309.     
  310.     def setAccess(self, allow, except_users):
  311.         '''
  312.         Set access control list.
  313.  
  314.         @param allow: whether to allow by default, otherwise deny
  315.         @type allow: bool
  316.         @param except_users: exception list
  317.         @type except_users: string list
  318.         '''
  319.         pass
  320.  
  321.     
  322.     def jobsQueued(self, only_tests = False):
  323.         '''
  324.         Find out whether jobs are queued for this printer.
  325.  
  326.         @param only_tests: whether to restrict search to test pages
  327.         @type only_tests: bool
  328.         @returns: list of job IDs
  329.         '''
  330.         ret = []
  331.         
  332.         try:
  333.             jobs = self.connection.getJobs()
  334.         except cups.IPPError:
  335.             return ret
  336.  
  337.         for id, attrs in jobs.iteritems():
  338.             
  339.             try:
  340.                 uri = attrs['job-printer-uri']
  341.                 uri = uri[uri.rindex('/') + 1:]
  342.             except:
  343.                 continue
  344.  
  345.             if uri != self.name:
  346.                 continue
  347.             
  348.             if (not only_tests or attrs.has_key('job-name')) and attrs['job-name'] == 'Test Page':
  349.                 ret.append(id)
  350.                 continue
  351.         
  352.         return ret
  353.  
  354.     
  355.     def testsQueued(self):
  356.         '''
  357.         Find out whether test jobs are queued for this printer.
  358.  
  359.         @returns: list of job IDs
  360.         '''
  361.         return self.jobsQueued(only_tests = True)
  362.  
  363.     
  364.     def setAsDefault(self):
  365.         '''
  366.         Set this printer as the system default.
  367.         '''
  368.         self.connection.setDefault(self.name)
  369.         (tmpfd, tmpfname) = tempfile.mkstemp()
  370.         os.remove(tmpfname)
  371.         
  372.         try:
  373.             resource = '/admin/conf/lpoptions'
  374.             self.connection.getFile(resource, fd = tmpfd)
  375.         except cups.HTTPError:
  376.             (s,) = None
  377.             if s == cups.HTTP_NOT_FOUND:
  378.                 return False
  379.             raise cups.HTTPError(s)
  380.         except:
  381.             s == cups.HTTP_NOT_FOUND
  382.  
  383.         f = os.fdopen(tmpfd, 'r+')
  384.         f.seek(0)
  385.         lines = f.readlines()
  386.         changed = False
  387.         i = 0
  388.         for line in lines:
  389.             if line.startswith('Default '):
  390.                 name = line.split(' ')[1]
  391.                 if name != self.name:
  392.                     lines[i] = 'Dest ' + line[8:]
  393.                     changed = True
  394.                 
  395.                 i += 1
  396.                 continue
  397.         
  398.         if changed:
  399.             f.seek(0)
  400.             f.writelines(lines)
  401.             f.truncate()
  402.             os.lseek(tmpfd, 0, os.SEEK_SET)
  403.             
  404.             try:
  405.                 self.connection.putFile(resource, fd = tmpfd)
  406.             except cups.HTTPError:
  407.                 (s,) = None
  408.                 return False
  409.             
  410.  
  411.         None<EXCEPTION MATCH>cups.HTTPError
  412.         return changed
  413.  
  414.  
  415.  
  416. def getPrinters(connection):
  417.     '''
  418.     Obtain a list of printers.
  419.  
  420.     @param connection: CUPS connection
  421.     @type connection: CUPS.Connection object
  422.     @returns: L{Printer} list
  423.     '''
  424.     printers = connection.getPrinters()
  425.     classes = connection.getClasses()
  426.     for name, printer in printers.iteritems():
  427.         printer = Printer(name, connection, **printer)
  428.         printers[name] = printer
  429.         if classes.has_key(name):
  430.             printer.class_members = classes[name]
  431.             printer.class_members.sort()
  432.             continue
  433.     
  434.     return printers
  435.  
  436.  
  437. def parseDeviceID(id):
  438.     '''
  439.     Parse an IEEE 1284 Device ID, so that it may be indexed by field name.
  440.  
  441.     @param id: IEEE 1284 Device ID, without the two leading length bytes
  442.     @type id: string
  443.     @returns: dict indexed by field name
  444.     '''
  445.     id_dict = { }
  446.     pieces = id.split(';')
  447.     for piece in pieces:
  448.         if piece.find(':') == -1:
  449.             continue
  450.         
  451.         (name, value) = piece.split(':', 1)
  452.         id_dict[name] = value
  453.     
  454.     if id_dict.has_key('MANUFACTURER'):
  455.         id_dict.setdefault('MFG', id_dict['MANUFACTURER'])
  456.     
  457.     if id_dict.has_key('MODEL'):
  458.         id_dict.setdefault('MDL', id_dict['MODEL'])
  459.     
  460.     if id_dict.has_key('COMMAND SET'):
  461.         id_dict.setdefault('CMD', id_dict['COMMAND SET'])
  462.     
  463.     for name in [
  464.         'MFG',
  465.         'MDL',
  466.         'CMD',
  467.         'CLS',
  468.         'DES',
  469.         'SN',
  470.         'S',
  471.         'P',
  472.         'J']:
  473.         id_dict.setdefault(name, '')
  474.     
  475.     id_dict['CMD'] = id_dict['CMD'].split(',')
  476.     return id_dict
  477.  
  478.  
  479. class Device:
  480.     '''
  481.     This class represents a CUPS device.
  482.     '''
  483.     
  484.     def __init__(self, uri, **kw):
  485.         '''
  486.         @param uri: device URI
  487.         @type uri: string
  488.         @param kw: device attributes
  489.         @type kw: dict
  490.         '''
  491.         self.uri = uri
  492.         self.device_class = kw.get('device-class', 'Unknown')
  493.         self.info = kw.get('device-info', '')
  494.         self.make_and_model = kw.get('device-make-and-model', 'Unknown')
  495.         self.id = kw.get('device-id', '')
  496.         uri_pieces = uri.split(':')
  497.         self.type = uri_pieces[0]
  498.         self.is_class = len(uri_pieces) == 1
  499.         self.id_dict = parseDeviceID(self.id)
  500.  
  501.     
  502.     def __repr__(self):
  503.         return '<cupshelpers.Device "%s">' % self.uri
  504.  
  505.     
  506.     def __cmp__(self, other):
  507.         '''
  508.         Compare devices by order of preference.
  509.         '''
  510.         if other == None:
  511.             return -1
  512.         if self.is_class != other.is_class:
  513.             if other.is_class:
  514.                 return -1
  515.             return 1
  516.         result = cmp(bool(self.id), bool(other.id))
  517.         return result
  518.  
  519.  
  520.  
  521. def getDevices(connection):
  522.     '''
  523.     Obtain a list of available CUPS devices.
  524.  
  525.     @param connection: CUPS connection
  526.     @type connection: cups.Connection object
  527.     @returns: a list of L{Device} objects
  528.     @raise cups.IPPError: IPP Error
  529.     '''
  530.     devices = connection.getDevices()
  531.     for uri, data in devices.iteritems():
  532.         device = Device(uri, **data)
  533.         devices[uri] = device
  534.         if device.info != 'Unknown' and device.make_and_model == 'Unknown':
  535.             device.make_and_model = device.info
  536.             continue
  537.     
  538.     return devices
  539.  
  540.  
  541. def activateNewPrinter(connection, name):
  542.     '''
  543.     Set a new printer enabled, accepting jobs, and (if necessary) the
  544.     default printer.
  545.  
  546.     @param connection: CUPS connection
  547.     @type connection: cups.Connection object
  548.     @param name: printer name
  549.     @type name: string
  550.     @raise cups.IPPError: IPP error
  551.     '''
  552.     connection.enablePrinter(name)
  553.     connection.acceptJobs(name)
  554.     if connection.getDefault() == None:
  555.         connection.setDefault(name)
  556.     
  557.  
  558.  
  559. def copyPPDOptions(ppd1, ppd2):
  560.     '''
  561.     Copy default options between PPDs.
  562.  
  563.     @param ppd1: source PPD
  564.     @type ppd1: cups.PPD object
  565.     @param ppd2: destination PPD
  566.     @type ppd2: cups.PPD object
  567.     '''
  568.     
  569.     def getPPDGroupOptions(group):
  570.         options = group.options[:]
  571.         for g in group.subgroups:
  572.             options.extend(getPPDGroupOptions(g))
  573.         
  574.         return options
  575.  
  576.     
  577.     def iteratePPDOptions(ppd):
  578.         for group in ppd.optionGroups:
  579.             for option in getPPDGroupOptions(group):
  580.                 yield option
  581.             
  582.         
  583.  
  584.     for option in iteratePPDOptions(ppd1):
  585.         if option.keyword == 'PageRegion':
  586.             continue
  587.         
  588.         new_option = ppd2.findOption(option.keyword)
  589.         if new_option and option.ui == new_option.ui:
  590.             value = option.defchoice
  591.             for choice in new_option.choices:
  592.                 if choice['choice'] == value:
  593.                     ppd2.markOption(new_option.keyword, value)
  594.                     _debugprint('set %s = %s' % (new_option.keyword, value))
  595.                     continue
  596.             
  597.     
  598.  
  599.  
  600. def setPPDPageSize(ppd, language):
  601.     '''
  602.     Set the PPD page size according to locale.
  603.  
  604.     @param ppd: PPD
  605.     @type ppd: cups.PPD object
  606.     @param language: language, as given by the first element of
  607.     locale.setlocale
  608.     @type language: string
  609.     '''
  610.     size = 'A4'
  611.     letter = [
  612.         'C',
  613.         'POSIX',
  614.         'en',
  615.         'en_US',
  616.         'en_CA',
  617.         'fr_CA']
  618.     for each in letter:
  619.         if language == each:
  620.             size = 'Letter'
  621.             continue
  622.     
  623.     
  624.     try:
  625.         ppd.markOption('PageSize', size)
  626.         _debugprint('set PageSize = %s' % size)
  627.     except:
  628.         _debugprint('Failed to set PageSize (%s not available?)' % size)
  629.  
  630.  
  631.  
  632. def missingPackagesAndExecutables(ppd):
  633.     '''
  634.     Check that all relevant executables for a PPD are installed.
  635.  
  636.     @param ppd: PPD
  637.     @type ppd: cups.PPD object
  638.     @returns: string list pair, representing missing packages and
  639.     missing executables
  640.     '''
  641.     
  642.     def pathcheck(name, path = '/usr/bin:/bin'):
  643.         p = name.find('%')
  644.         if p != -1:
  645.             name = name[:p]
  646.         
  647.         if len(name) == 0:
  648.             return 'true'
  649.         if name[0] == '/':
  650.             if os.access(name, os.X_OK):
  651.                 _debugprint('%s: found' % name)
  652.                 return name
  653.             _debugprint('%s: NOT found' % name)
  654.             return None
  655.         name[0] == '/'
  656.         if name.find('=') != -1:
  657.             return 'builtin'
  658.         if name in (':', '.', '[', 'alias', 'bind', 'break', 'cd', 'continue', 'declare', 'echo', 'else', 'eval', 'exec', 'exit', 'export', 'fi', 'if', 'kill', 'let', 'local', 'popd', 'printf', 'pushd', 'pwd', 'read', 'readonly', 'set', 'shift', 'shopt', 'source', 'test', 'then', 'trap', 'type', 'ulimit', 'umask', 'unalias', 'unset', 'wait'):
  659.             return 'builtin'
  660.         for component in path.split(':'):
  661.             file = component.rstrip(os.path.sep) + os.path.sep + name
  662.             if os.access(file, os.X_OK):
  663.                 _debugprint('%s: found' % file)
  664.                 return file
  665.         
  666.         _debugprint('%s: NOT found in %s' % (name, path))
  667.  
  668.     pkgs_to_install = []
  669.     exes_to_install = []
  670.     exe = None
  671.     exepath = None
  672.     attr = ppd.findAttr('FoomaticRIPCommandLine')
  673.     if attr:
  674.         cmdline = attr.value.replace('&&\n', '')
  675.         cmdline = cmdline.replace('"', '"')
  676.         cmdline = cmdline.replace('<', '<')
  677.         cmdline = cmdline.replace('>', '>')
  678.         if cmdline.find('(') != -1 or cmdline.find('&') != -1:
  679.             cmdline = ''
  680.         
  681.         pipes = cmdline.split(';')
  682.         for pipe in pipes:
  683.             cmds = pipe.strip().split('|')
  684.             for cmd in cmds:
  685.                 args = cmd.strip().split(' ')
  686.                 exe = args[0]
  687.                 exepath = pathcheck(exe)
  688.                 if not exepath:
  689.                     break
  690.                 
  691.                 if os.path.basename(exepath) == 'gs':
  692.                     argn = len(args)
  693.                     argi = 1
  694.                     search = '-sIjsServer='
  695.                     while argi < argn:
  696.                         arg = args[argi]
  697.                         if arg.startswith(search):
  698.                             exe = arg[len(search):]
  699.                             exepath = pathcheck(exe)
  700.                             break
  701.                         
  702.                         argi += 1
  703.                     continue
  704.             
  705.             if not exepath:
  706.                 break
  707.                 continue
  708.         
  709.     
  710.     if exepath or not exe:
  711.         (tmpfd, tmpfname) = tempfile.mkstemp()
  712.         os.unlink(tmpfname)
  713.         ppd.writeFd(tmpfd)
  714.         os.lseek(tmpfd, 0, os.SEEK_SET)
  715.         f = os.fdopen(tmpfd, 'r')
  716.         search = '*cupsFilter:'
  717.         for line in f.readlines():
  718.             if line.startswith(search):
  719.                 line = line[len(search):].strip().strip('"')
  720.                 
  721.                 try:
  722.                     (mimetype, cost, exe) = line.split(' ')
  723.                 except:
  724.                     continue
  725.  
  726.                 exepath = pathcheck(exe, '/usr/lib/cups/filter:/usr/lib64/cups/filter')
  727.                 continue
  728.         
  729.     
  730.     if exe and not exepath:
  731.         p = exe.find('%')
  732.         if p != -1:
  733.             exe = exe[:p]
  734.         
  735.         pkgs = {
  736.             'gs': 'ghostscript',
  737.             'perl': 'perl',
  738.             'foo2oak-wrapper': None,
  739.             'pnm2ppa': 'pnm2ppa',
  740.             'c2050': 'c2050',
  741.             'c2070': 'c2070',
  742.             'cjet': 'cjet',
  743.             'lm1100': 'lx',
  744.             'esc-m': 'min12xxw',
  745.             'min12xxw': 'min12xxw',
  746.             'pbm2l2030': 'pbm2l2030',
  747.             'pbm2l7k': 'pbm2l7k',
  748.             'pbm2lex': 'pbm2l7k',
  749.             'hpijs': 'hpijs',
  750.             'ijsgutenprint.5.0': 'gutenprint',
  751.             'rastertogutenprint.5.0': 'gutenprint-cups',
  752.             'commandtoepson': 'gutenprint-cups',
  753.             'commandtocanon': 'gutenprint-cups' }
  754.         
  755.         try:
  756.             pkg = pkgs[exe]
  757.         except:
  758.             pkg = None
  759.  
  760.         if pkg:
  761.             _debugprint('%s included in package %s' % (exe, pkg))
  762.             pkgs_to_install.append(pkg)
  763.         else:
  764.             exes_to_install.append(exe)
  765.     
  766.     return (pkgs_to_install, exes_to_install)
  767.  
  768.  
  769. def _main():
  770.     c = cups.Connection()
  771.     for device in getDevices(c).itervalues():
  772.         print device.uri, device.id_dict
  773.     
  774.  
  775. if __name__ == '__main__':
  776.     _main()
  777.  
  778.